package com.heiye.blog.ai.model.dashscope;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.heiye.blog.ai.advisor.DashScopeAdvisor;
import lombok.*;
import reactor.core.publisher.Flux;

import java.util.*;

/**
 * @author: heiye
 * @date: 2025/11/09 下午11:18
 * @version: v1.0.0
 * @description: 百炼模型聊天客户端控制
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DashScopeChatClient {

    private String userMessage;

    private List<DashScopeAdvisor> advisors;

    private DashScopeChatOptions options;

    /**
     * 添加 Advisor
     *
     * @param advisors
     */
    public void advisors(List<DashScopeAdvisor> advisors) {
        if (CollUtil.isNotEmpty(advisors)) {
            this.advisors = new ArrayList<>(advisors);
        }

        // 按order排序
        this.advisors.sort(Comparator.comparingInt(DashScopeAdvisor::getOrder));
    }


    /**
     * 构建并调用百炼模型
     *
     * @return
     */
    @SneakyThrows
    public Flux<GenerationResult> stream() {

        Boolean incrementalOutput = this.options.getIncrementalOutput();

        // 构建调用百炼模型的 message
        Message message = Message.builder()
                .role(Role.USER.getValue())
                .content(userMessage)
                .build();

        // 构建调用百炼模型的参数
        GenerationParam generationParam = GenerationParam.builder()
                .model(this.options.getModel())
                .apiKey(this.options.getApiKey())
                .enableThinking(this.options.getEnableThink())
                // 在流式输出模式下是否开启增量输出。
                .incrementalOutput(Objects.nonNull(incrementalOutput) ? incrementalOutput : false)
                // 模型在生成回复时是否使用互联网搜索结果进行参考。
                .enableSearch(this.options.getNetworkSearch())
                .temperature(this.options.getTemperature())
                .messages(Collections.singletonList(message))
                .build();

        // Advisor 预处理请求
        GenerationParam executedGenerationParam = executeRequestAdvisors(generationParam);

        // 构建调用百炼模型
        Generation generation = new Generation();

        // 调用百炼模型后用 Flux 包装
        Flux<GenerationResult> flux = Flux.from(generation.streamCall(executedGenerationParam));

        // 执行响应 Advisor
        Flux<GenerationResult> generationResultFlux = executeStreamAdvisors(flux);

        // 返回流式结果
        return generationResultFlux;
    }

    /**
     * Advisor 预处理请求
     *
     * @param generationParam
     * @return
     */
    public GenerationParam executeRequestAdvisors(GenerationParam generationParam) {

        GenerationParam processedParam = generationParam;

        // 遍历 Advisor
        for (DashScopeAdvisor advisor : this.advisors) {
            processedParam = advisor.adviseRequest(processedParam);
        }

        return processedParam;
    }

    /**
     * 执行响应 Advisor 链
     *
     * @param fluxResult
     * @return
     */
    public Flux<GenerationResult> executeStreamAdvisors(Flux<GenerationResult> fluxResult) {

        Flux<GenerationResult> processedFlux = fluxResult;

        // 执行响应 Advisor
        for (DashScopeAdvisor advisor : this.advisors) {
            processedFlux = advisor.adviseStream(processedFlux);
        }

        return processedFlux;
    }
}
